package biz.yfsoft.app.fastframework.plugin.icbc;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Map;

import biz.yfsoft.app.fastframework.kit.DateKit;
import cn.com.infosec.icbc.ReturnValue;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;

/**
 * icbc 正常的B2B支付接口
 * @author Frank
 *
 */
public class B2BIcbcPay {

	private static B2BIcbcPay _me;
	
	//在银行接口端设置的商户代码
	private String shopCode = "1103EC14197195";
	//支付之后的回调地址
	private String notifyUrl = "http://fast.yfsoft.info/fastframework/admin/notify/payNotify";
	
	//商城账号
	private String shopAcc = "1103046219200013401";
	
	//接口地址
	private String postUrl = "https://corporbank.icbc.com.cn/servlet/ICBCINBSEBusinessServlet";
	//调试模式
	private String mode = "DEBUG";
	
	private String date = null;
	
	private static final String BASE_SIGNSTR = "APIName=B2B&APIVersion=001.001.001.001&Shop_code={0}&MerchantURL={1}&ContractNo={2}&ContractAmt={3}&Account_cur=001&JoinFlag=2&SendType=0&TranTime={4}&Shop_acc_num={5}&PayeeAcct={6}";
	
	public static void config(final byte[] bcert,final byte[] bkey,JSONObject configJson){
		_me = new B2BIcbcPay();
		String pass =  configJson.containsKey("password")?configJson.getString("password"):"123456";
		_me.keyPass = pass.toCharArray();
		_me.bcert = bcert;
		_me.bkey = bkey;
		byte[] EncCert = ReturnValue.base64enc(bcert);
		_me.certBase64 = new String(EncCert).toString();
		_me.configJson = configJson;
		
		if(configJson.containsKey("shopCode"))
			_me.shopCode = configJson.getString("shopCode");
		if(configJson.containsKey("notifyUrl"))
			_me.notifyUrl = configJson.getString("notifyUrl");
		if(configJson.containsKey("shopAcc"))
			_me.shopAcc = configJson.getString("shopAcc");
		if(configJson.containsKey("postUrl"))
			_me.postUrl = configJson.getString("postUrl");
		if(configJson.containsKey("mode"))
			_me.mode = configJson.getString("mode");
		if(configJson.containsKey("date")){
			_me.date = configJson.getString("date");
		}
	}
	
	public static B2BIcbcPay me(){
		if(_me == null){
			//插件未启动
			//TODO..给予错误警告
		}
		return _me;
	}
	
	private B2BIcbcPay(){}
	
	@SuppressWarnings("unused")
	private byte[] bcert,bkey;
	
	private String certBase64;
	
	private char[] keyPass;
	
	private JSONObject configJson;
	
	public JSONObject getConfig(){
		return this.configJson;
	}
	
	public String getCertBase64(){
		return certBase64;
	}
	
	public String base64enc(String tranData){
		byte[] byteSrc = tranData.getBytes();
		try {
			byte[] sign =ReturnValue.sign(byteSrc,byteSrc.length,bkey,keyPass);
			byte[] EncSign = ReturnValue.base64enc(sign);
		    String SignMsgBase64 = new String(EncSign).toString();
		    return SignMsgBase64;
		} catch (InvalidKeyException | NoSuchProviderException
				| NoSuchAlgorithmException | SignatureException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public byte[] base64dec(byte[] src){
		//byte[] DecSign = ReturnValue.base64dec(EncSign);
		return null;
	}
	
	public String verifySign(String enc){
		
		return null;
	}
	
	public void pay(Controller ctrl,Map<String,Object> order,Map<String,Object> goods){
		Object payAcc = ("DEBUG".equalsIgnoreCase(mode)?shopAcc:order.get("seller"));//收款账号，调试模式下会打款给商城
		//如果是测试系统，则需要进行时间字段的调整
		String trantime = null;
		if(this.date == null){
			//没有使用配置的时间偏移
			trantime = DateKit.toStr(new Date(),"YYYYMMddHHmmss");
		}else{
			trantime = this.date + DateKit.toStr(new Date(),"HHmmss");
		}
		ctrl.setAttr("order", order);
		ctrl.setAttr("goods",goods);
		ctrl.setAttr("trantime", trantime);
		ctrl.setAttr("cert", this.certBase64);
		ctrl.setAttr("shopCode", shopCode);
		ctrl.setAttr("shopAcc", shopAcc);
		ctrl.setAttr("payAcc", payAcc);//保证正式环境中的号可以调试
		ctrl.setAttr("notifyUrl", notifyUrl);
		ctrl.setAttr("config", configJson);
		ctrl.setAttr("postUrl", postUrl);
		
		
		order.put("createtime",trantime);
		
		String signstr = MessageFormat.format(BASE_SIGNSTR,
				shopCode,
				notifyUrl,
				order.get("id"),
				order.get("amount"),
				trantime,
				shopAcc,
				payAcc
				);
		signstr = base64enc(signstr);
		ctrl.setAttr("signstr", signstr);
		
		ctrl.render("/pay.jsp");
	}
}
